package cn.hc.tool.exec.service;

import cn.hc.tool.common.util.ClassUtil;
import cn.hc.tool.common.util.CollectionUtil;
import cn.hc.tool.common.util.StringUtil;
import cn.hc.tool.exec.utils.HcSpringBeanUtil;
import lombok.NonNull;
import org.springframework.stereotype.Service;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author huangchao E-mail:fengquan8866@163.com
 * @version 创建时间：2024/9/24 17:04
 */
@Service
public class HcBeanService {

    /**
     * 获取bean
     *
     * @param className 类路径
     * @param beanName  实例名
     */
    public Object getBean(String className, String beanName) throws ClassNotFoundException {
        if (!StringUtil.isBlank(className)) {
            Class<?> c = Class.forName(className);
            return this.getBean(c, beanName);
        }
        if (!StringUtil.isBlank(beanName)) return HcSpringBeanUtil.getBean(beanName);
        return null;
    }

    public <V> V getBean(@NonNull Class<V> c, String beanName) {
        if (!StringUtil.isBlank(beanName)) return HcSpringBeanUtil.getBean(c, beanName);
        Map<String, V> beansOfType = HcSpringBeanUtil.getBeansOfType(c);
//            if (beansOfType.containsKey(beanName)) return beansOfType.get(beanName);
        for (V o : beansOfType.values()) {
            return o;
        }
        return null;
    }

    /**
     * 筛选符合的方法
     *
     * @param methods 方法列表
     * @param arr     参数集合
     * @return 最符合的方法
     */
    public Method getMethod(String className, List<Method> methods, List<Object> arr) {
        List<Method> list = new ArrayList<Method>();
        // 先筛选参数个数相等的方法
        for (Method m : methods) {
            if (arr.size() == m.getParameterTypes().length) {
                list.add(m);
            }
        }
        // 筛选 arr.length < 参数个数 的方法
        if (list.isEmpty()) {
            for (Method m : methods) {
                if (arr.size() < m.getParameterTypes().length) {
                    list.add(m);
                }
            }
        }
        if (list.size() == 1) {
            return list.get(0);
        }
        // 去掉Object类型方法
        for (int i = list.size() - 1; i >= 0; i--) {
            Class<?>[] parameterTypes = list.get(i).getParameterTypes();
            for (Class<?> cl : parameterTypes) {
                if (cl == Object.class) {
                    list.remove(i);
                    break;
                }
            }
        }
        if (list.isEmpty()) {
            return null;
        }
        if (list.size() == 1) {
            return list.get(0);
        } else {
            for (Method m : list) {
                if (m.getDeclaringClass().getName().equals(className)) {
                    return m;
                }
            }
        }
        // TODO 暂时取最后一个方法
        return list.get(list.size() - 1);
    }

    @Deprecated
    public Method getMethod(String className, String methodName, Class[] cls) throws ClassNotFoundException, NoSuchMethodException {
        return this.getMethod(className, methodName, cls, null);
    }

    public Method getMethod(String className, String methodName, Class[] cls, List<Object> arr) throws ClassNotFoundException, NoSuchMethodException {
        Class<?> aClass = Class.forName(className);
        Class<?> realClass;
        if (ClassUtil.isInterface(aClass)) {
            Object bean = getBean(className, null);
            realClass = bean.getClass();
        } else {
            realClass = aClass;
        }
        if (cls != null) {
            return ClassUtil.getDeclaredMethod(realClass, methodName, cls);
        }
        List<Method> declareMethods = ClassUtil.getAllDeclareMethodsByName(realClass, methodName);
        if (CollectionUtil.isEmpty(declareMethods)) {
            return null;
        }
        if (declareMethods.size() > 1 && !CollectionUtil.isEmpty(arr)) {
            return getMethod(className, declareMethods, arr);
        }
        return declareMethods.get(0);
    }
}
